﻿using CoreDomain;
using DomainService.IService;
using Infrastructure;
using Infrastructure.IRepository;
using Infrastructure.Repository;
using Model.BusinessModel;
using Model.BusinessModel.InPut;
using Model.BusinessModel.OutPut;
using Model.DomainModel;
using Model.Flow;
using Model.OverallAtuhModel;
using Utility;
using Utility.Enum;

namespace DomainService.Service
{
    /// <summary>
    /// 流程服务实现
    /// </summary>
    public class FlowService : IFlowService
    {
        #region 构造实例化

        /// <summary>
        /// 表单仓储接口
        /// </summary>
        private readonly IFormRepository _formRepository;

        /// <summary>
        /// 流程仓储接口
        /// </summary>
        private readonly IFlowRepository _flowRepository;

        /// <summary>
        /// 流程节点仓储接口
        /// </summary>
        private readonly IFlowNodeConfigRepository _flowNodeConfigRepository;

        /// <summary>
        /// 流程申请仓储接口
        /// </summary>
        private readonly IFlowApplyRepository _flowApplyRepository;

        /// <summary>
        /// 基础服务
        /// </summary>
        private readonly IBaseService _baseService;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="formRepository"></param>
        /// <param name="baseService"></param>
        /// <param name="flowRepository"></param>
        /// <param name="flowNodeConfigRepository"></param>
        /// <param name="flowApplyRepository"></param>
        public FlowService(IFormRepository formRepository, IBaseService baseService, IFlowRepository flowRepository, IFlowNodeConfigRepository flowNodeConfigRepository, IFlowApplyRepository flowApplyRepository)
        {
            _formRepository = formRepository;
            _flowRepository = flowRepository;
            _baseService = baseService;
            _flowNodeConfigRepository = flowNodeConfigRepository;
            _flowApplyRepository = flowApplyRepository;
        }

        #endregion

        #region 接口实现

        /// <summary>
        /// 新增流程信息
        /// </summary>
        /// <param name="flow">实体模型</param>
        /// <returns></returns>
        public ReceiveStatus Insert(FlowInput flow)
        {
            ReceiveStatus receiveStatus = new();

            try
            {
                //新增前验证
                if (string.IsNullOrWhiteSpace(flow.flow.FormId))
                    return ExceptionHelper.CustomException("请选择流程绑定表单!");
                var formModel = _formRepository.GetByKey(flow.flow.FormId, BaseSqlRepository.form_selectByKeySql);
                if (formModel == null)
                    return ExceptionHelper.CustomException("选择的表单不存在或已删除!");

                var flowModel = _flowRepository.GetFlowByFlowName(flow.flow.FlowName);
                if (flowModel != null && flow.flow.FlowName == flowModel.FlowName)
                    return ExceptionHelper.CustomException(string.Format("流程名称【{0}】重复，请重新填写!", flow.flow.FlowName));

                var flowData = JsonHelper.JsonStrToEntity<FlowModel>(flow.flow.FlowContent);
                flow.flow.FlowContent = JsonHelper.SerializeObjToJson(flowData);
                var data = FlowCore.VerifyFlow(flowData);
                if (!data.Item2)
                    return ExceptionHelper.CustomException(data.Item1);

                flow.flow.FlowId = Guid.NewGuid().ToString();
                flow.flowNodeConfigList = flow.flowNodeConfigList.Where(f => f.NodeType != FlowNodeTypeEnum.input && f.NodeType != FlowNodeTypeEnum.output).ToList();
                foreach (var item in flow.flowNodeConfigList)
                {
                    item.FlowId = flow.flow.FlowId;
                    item.Id = Guid.NewGuid().ToString();
                    item.CreateTime = flow.flow.CreateTime;
                    item.CreateUserKey = flow.flow.CreateUserKey;
                }
                TransactionHelper.ExecuteTransaction(() =>
                {
                    _flowRepository.Insert(flow.flow, BaseSqlRepository.flow_insertSql);

                    _flowNodeConfigRepository.BulkInsert(flow.flowNodeConfigList);
                });
            }
            catch (Exception ex)
            {
                receiveStatus.success = false;
                receiveStatus.code = CodeStatuEnum.Error;
                receiveStatus.msg = ex.Message;
            }


            return receiveStatus;
        }

        /// <summary>
        /// 更新流程信息
        /// </summary>
        /// <param name="examineForm">实体模型</param>
        /// <returns></returns>
        public ReceiveStatus Update(FlowInput flow)
        {
            ReceiveStatus receiveStatus = new();

            try
            {
                //更新前验证
                if (string.IsNullOrWhiteSpace(flow.flow.FormId))
                    return ExceptionHelper.CustomException("请选择流程绑定表单!");
                var formModel = _formRepository.GetByKey(flow.flow.FormId, BaseSqlRepository.form_selectByKeySql);
                if (formModel == null)
                    return ExceptionHelper.CustomException("选择的表单不存在或已删除!");

                var flowModel = _flowRepository.GetFlowByFlowName(flow.flow.FlowName);
                if (flowModel != null && flow.flow.FlowName == flowModel.FlowName && flow.flow.FlowId != flowModel.FlowId)
                    return ExceptionHelper.CustomException(string.Format("流程名称【{0}】重复，请重新填写!", flow.flow.FlowName));

                var flowData = JsonHelper.JsonStrToEntity<FlowModel>(flow.flow.FlowContent);
                flow.flow.FlowContent = JsonHelper.SerializeObjToJson(flowData);
                var data = FlowCore.VerifyFlow(flowData);
                if (!data.Item2)
                    return ExceptionHelper.CustomException(data.Item1);

                flow.flowNodeConfigList = flow.flowNodeConfigList.Where(f => f.NodeType != FlowNodeTypeEnum.input && f.NodeType != FlowNodeTypeEnum.output).ToList();
                foreach (var item in flow.flowNodeConfigList)
                {
                    item.FlowId = flow.flow.FlowId;
                    item.Id = Guid.NewGuid().ToString();
                    item.CreateTime = flow.flow.CreateTime;
                    item.CreateUserKey = flow.flow.CreateUserKey;
                }
                TransactionHelper.ExecuteTransaction(() =>
                {
                    _flowRepository.Update(flow.flow, BaseSqlRepository.flow_updateSql);
                    //先删除在更新
                    _flowNodeConfigRepository.BulkDeleteByFlowId(flow.flowNodeConfigList);
                    _flowNodeConfigRepository.BulkInsert(flow.flowNodeConfigList);
                });
            }
            catch (Exception ex)
            {
                receiveStatus.success = false;
                receiveStatus.code = CodeStatuEnum.Error;
                receiveStatus.msg = ex.Message;
            }
            return receiveStatus;
        }

        /// <summary>
        /// 获取所有流程
        /// </summary>
        /// <param name="pageResultModel"></param>
        /// <returns></returns>
        public PageResultModel<FlowOutPut> GetAllFlow(PageResultModel pageResultModel)
        {
            pageResultModel.tableField = " f.*,fm.FormName  ";
            pageResultModel.tableName = @" Flow as f inner join Form as fm on f.FormId = fm.FormId  ";
            pageResultModel.orderByField = " f.CreateTime ";
            pageResultModel.sortType = " desc ";

            //数据权限
            var menuId = _baseService.GetCurrentMenuId();
            var authWhere = _flowRepository.GetDataAuthWhere(menuId, "f", RuleTypeEnum.DataRowRule);
            pageResultModel.selectWhere = authWhere;

            var list = _flowRepository.GetPageList<FlowOutPut>(pageResultModel);

            var userList = MemoryCacheHelper.GetCachedDataByKey<List<SysUser>>(ConstHelper.UserCacheKey);
            var depList = MemoryCacheHelper.GetCachedDataByKey<List<SysDepartment>>(ConstHelper.DepartmentCacheKey);
            foreach (var item in list.data)
            {
                item.CreateUserName = userList.data?.Find(f => f.UserId == item.CreateUserKey)?.UserName ?? string.Empty;
                item.DepartmentName = depList.data?.Find(f => f.Id == item.DepartmentId)?.DepartmentName ?? string.Empty;
            }

            return list;
        }

        /// <summary>
        ///获取所有流程
        /// </summary>
        /// <returns></returns>
        public ReceiveStatus<List<Flow>> GetAllFlowList()
        {
            ReceiveStatus<List<Flow>> receiveStatus = new();
            var list = _flowRepository.GetAll(BaseSqlRepository.form_selectAllSql);
            receiveStatus.data = list;
            return receiveStatus;
        }

        /// <summary>
        /// 根据主键获取流程
        /// </summary>
        /// <param name="flowId">流程主键</param>
        /// <returns></returns>
        public ReceiveStatus<Flow> GetFlowByFlowId(string flowId)
        {
            ReceiveStatus<Flow> receiveStatus = new();
            var flowModel = _flowRepository.GetByKey(flowId, BaseSqlRepository.flow_selectByKeySql);
            if (flowModel == null)
                return ExceptionHelper<Flow>.CustomExceptionData("流程不存在或已删除!");
            var model = _flowRepository.GetByKey(flowId, BaseSqlRepository.flow_selectByKeySql);
            receiveStatus.data = model;
            return receiveStatus;
        }

        /// <summary>
        /// 获取流程节点配置
        /// </summary>
        /// <param name="flowId">流程id</param>
        /// <param name="flowNodeId">节点id</param>
        /// <returns></returns>
        public ReceiveStatus<FlowNodeConfigOutPut> GetExpireDate(string flowId, string flowNodeId)
        {
            FlowNodeConfigOutPut model = new FlowNodeConfigOutPut();
            ReceiveStatus<FlowNodeConfigOutPut> receiveStatus = new();
            var flowModel = _flowRepository.GetByKey(flowId, BaseSqlRepository.flow_selectByKeySql);
            if (flowModel == null)
                return ExceptionHelper<FlowNodeConfigOutPut>.CustomExceptionData("流程不存在或已删除!");
            var nodeCofigModel = _flowNodeConfigRepository.GetExpireDate(flowId, flowNodeId);
            if (nodeCofigModel == null)
            {
                receiveStatus.code = CodeStatuEnum.IgnoreError;
                receiveStatus.success = false;
                return receiveStatus;
            }


            var expireDateModel = JsonHelper.JsonStrToEntity<ExpireDateModel>(nodeCofigModel.ExpireConfig);
            var fieldAuthConfigList = JsonHelper.JsonStrToEntity<List<SelectOutPut>>(nodeCofigModel.FieldAuthConfig);
            model.ExpireDateModel = expireDateModel == null ? new ExpireDateModel() : expireDateModel;
            model.FieldAuthConfigList = fieldAuthConfigList;
            receiveStatus.data = model;
            return receiveStatus;
        }

        /// <summary>
        /// 更新数据状态
        /// </summary>
        /// <param name="input">输入模型</param>
        /// <returns></returns>
        public ReceiveStatus UpdateFlowDataState(UpdateDataStateInput input)
        {
            ReceiveStatus receiveStatus = new();
            if (input.Ids.Count == 0)
                return ExceptionHelper.CustomException("请选择更新数据");
            if (input.DataState == 0)
                return ExceptionHelper.CustomException("请设置数据状态");

            if (input.DataState == DataStateEnum.Delete)
            {
                foreach (var item in input.Ids)
                {
                    var flowApplyList = _flowApplyRepository.GetFlowApplyByFlowId(item).Where(f => f.DataState != DataStateEnum.Delete).ToList();
                    if (flowApplyList.Count > 0)
                    {
                        return ExceptionHelper.CustomException("该流程已存在申请记录,不能删除");
                    }
                }
            }

            _flowRepository.UpdateFlowDataState(input);
            return receiveStatus;
        }

        /// <summary>
        /// 获取部门流程树形结构
        /// </summary>
        /// <param name="corporationKey">公司key</param>
        /// <returns></returns>
        public ReceiveStatus<List<TreeOutPut>> GetDepartmentFlow(string corporationKey)
        {
            ReceiveStatus<List<TreeOutPut>> receiveStatus = new ReceiveStatus<List<TreeOutPut>>();
            if (string.IsNullOrWhiteSpace(corporationKey))
                return ExceptionHelper<List<TreeOutPut>>.CustomExceptionData("不存在公司信息!");
            var depList = MemoryCacheHelper.GetCachedDataByKey<List<TreeOutPut>>(ConstHelper.DepartmentTreeCacheKey);
            if (depList.success == false)
                ExceptionHelper.ThrowBusinessException("部门缓存不存在或已过期,请重置缓存");

            var flowList = _flowRepository.GetAllFlow().Where(f => f.DataState == DataStateEnum.Enable).ToList();
            var departmentList = JsonHelper.DeepCopy(depList);
            //把流程数据添加到节点上
            if (!departmentList.success)
            {
                return ExceptionHelper<List<TreeOutPut>>.CustomExceptionData("部门信息查询失败!");
            }
            if (departmentList.data == null || departmentList.data.Count == 0)
            {
                return ExceptionHelper<List<TreeOutPut>>.CustomExceptionData("不存在部门信息!");
            }
            if (flowList?.Count > 0)
            {
                foreach (var item in flowList)
                {
                    var treeNode = new TreeOutPut()
                    {
                        key = item.FlowId,
                        pKey = item.DepartmentId,
                        label = item.FlowName,
                        isLeaf = true,
                        nodeType = (int)TreeNodeTypeEnum.Flow,
                        children = new List<TreeOutPut>()
                    };
                    TreeCore.AddTreeNode(departmentList.data, treeNode);
                }
            }
            receiveStatus.data = departmentList.data;

            return receiveStatus;
        }

        /// <summary>
        /// 根据流程id获取流程和表单数据
        /// </summary>
        /// <param name="flowId">流程id</param>
        /// <returns></returns>
        public ReceiveStatus<FlowOrFormOutPut> GetFlowOrFormByFlowId(string flowId)
        {
            ReceiveStatus<FlowOrFormOutPut> receiveStatus = new ReceiveStatus<FlowOrFormOutPut>();
            if (string.IsNullOrEmpty(flowId))
                return ExceptionHelper<FlowOrFormOutPut>.CustomExceptionData("请选择申请流程!");
            var flowOrForm = _flowRepository.GetFlowByFlowId(flowId);
            if (flowOrForm == null)
                return ExceptionHelper<FlowOrFormOutPut>.CustomExceptionData("当前流程不存在或已删除!");
            receiveStatus.data = flowOrForm;
            return receiveStatus;
        }

        #endregion
    }
}
